<?php
/**
* $Id: user.php 2942 2009-11-30 10:48:18Z huong.pham $
* Application user component
* 
* @author Hung Nguyen
*/
require_once('appcomponent.php');
class User extends AppComponent
{
    protected $isGuest = true;
    
    public function __construct(){
        parent::__construct();
    }
    
    public function createIdentity($username, $password){
        $class = $this->config('IdentityManager', 'UserIdentityDatabase');
        try{
            $ui = new $class($username, $password);
        }catch(Exception $ex){
            throw new Exception($class . ' is not defined in your project.');
        }
        return $ui;
    }
    
    /**
    * Log an authorized user identity in and save user's info
    * 
    * @param mixed $ui
    */
    public function login($ui){
        $user_data = $this->CI->session->userdata('__USER__');  
        $newStates = $ui->setUserState();
        foreach($newStates as $key => $value)
            $user_data[$key] = $value;
        //$user_data['username'] = $ui->username;
        $user_data['is_guest'] = false;
        
        //Set roles
        $roles = array();
        if (($roleManager = $this->config('RoleManager', null)) != null){
            $this->CI->load->library($roleManager);
            $rm = strtolower($roleManager);
            $roles = $this->CI->$rm->getRoles($user_data);
        }
        $user_data['roles'] = $roles;
        $this->CI->session->set_userdata('__USER__', $user_data);
        
        $this->isGuest = false;
    }
    
    /**
    * Log user out
    * 
    */
    public function logout(){
        $this->CI->session->unset_userdata('__USER__');
        $user_data['is_guest'] = true;
        $this->CI->session->set_userdata('__USER__', $user_data);
    }
    
    /**
    * If the user is guest
    */
    public function isGuest(){
        return $this->is_guest;
    }
    
    /**
    * Get user state info. This allow you to use $this->user->name
    * This is a shortcut of $this->user->getState($name)
    * 
    * @param mixed $name
    */
    public function __get($name){
        return $this->getState($name);
    }
    
    
    public function setRedirectUrl($url){
        $this->setState('redirect_url', $url);
    }
    
    public function getRedirectUrl(){
        $user_data = $this->CI->session->userdata('__USER__');
        return $this->getState('redirect_url');
    }
    
    public function setState($name, $value){
        $user_data = $this->CI->session->userdata('__USER__');
        if (!is_array($user_data)) $user_data = array();
        $user_data[$name] = $value;
        $this->CI->session->set_userdata('__USER__', $user_data);
    }
    
    public function getState($name){
        $user_data = $this->CI->session->userdata('__USER__');
        if (is_array($user_data) && array_key_exists($name, $user_data))
            return $user_data[$name];
        elseif($name == 'is_guest')
            return true;
        else
            return null;    
    }
    
}  

/**
* Abstract class UserIdentityBase
* The authorize method is not implemented here so this class is abstract and 
* you should not use it directly
*/
abstract class UserIdentity extends AppComponent implements IIdentity
{
    protected $username;
    protected $password;
    
    const ERR_INVALID_IDENTITY = 1;
    const ERR_INACTIVE_IDENTITY = 2;
    const ERR_NONE = 0;
    
    public function __construct($username, $password){
        parent::__construct();

        $this->username = $username;
        $this->password = $password;
    }
    
//    public abstract function authorize();
    
    public function setUserState(){
        //Nothing to do here
    }
    
    public function getUsername(){ return $this->username;}
    
}


class UserIdentityDatabase extends UserIdentity
{
    //UserIdentity object
    protected $user;
    
    
    public function authorize(){
        $this->CI->load->model('MUser');
        
        //Check username and password match
        $this->CI->MUser->selectDetails();
        $user = $this->CI->MUser->getByEmailAndPassword($this->username, $this->prep_password($this->password)); 
        if(empty($user)) 
        {
            return self::ERR_INVALID_IDENTITY;
        } 
        else if($user['is_activated'] == AppContants::INACTIVE_STATUS)
        {
            return self::ERR_INACTIVE_IDENTITY;
        }
        else 
        {
            $this->user = $user;
            return self::ERR_NONE;
        }
    }
    
    public function setUserState(){
        return array(   'Id' => $this->user['id'],
                        'first_name' => $this->user['first_name'],
                        'email' => $this->user['email'],
                        'username' => $this->user['username']);
    }
    
    /*
    Function:  _prep_password($password)
    Purpose:   Salt the password with an encryption key
    Input:       password string
    Output:       password string plus encryption key     
    *   @access : public
    *   @param :  string
    *   @return : string 
    */    
    function prep_password($password)
    {
         $mykey = md5($password . $this->config('encryption_key'));
         return $mykey;
    }
}

class UserIdentityConfig extends UserIdentity
{
    public function authorize(){
        $valid_username = $this->config('AdminUser', 'admin');
        $valid_password = $this->config('AdminPassword', 'admin');
        
        if ($this->username == $valid_username && $this->password == $valid_password)
            return true;
            
        return false;
    }
}

/**
* User Identity interface, define method needed in an UserIdentity class for authorization and persist user info
*/
interface IIdentity{
    public function authorize();
    public function setUserState();
}
?>